package com.kly.order.serviceImpl;

import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.fqgj.common.api.Response;
import com.fqgj.common.utils.CollectionUtils;
import com.fqgj.exception.common.ApplicationException;
import com.google.api.client.util.Lists;
import com.kly.dto.AllProductDto;
import com.kly.dto.ProductBenefitDto;
import com.kly.dto.ProductCategoryDto;
import com.kly.dto.ProductDto;
import com.kly.enums.TradeResultStatus;
import com.kly.order.ServiceUtils;
import com.kly.order.db.dao.BenefitsDao;
import com.kly.order.db.dao.ProductBenefitsDao;
import com.kly.order.db.dao.ProductCategoryDao;
import com.kly.order.db.dao.ProductDao;
import com.kly.order.db.entity.BenefitsEntity;
import com.kly.order.db.entity.ProductBenefitsEntity;
import com.kly.order.db.entity.ProductCategoryEntity;
import com.kly.order.db.entity.ProductEntity;
import com.kly.order.mapper.ProductMapper;
import com.kly.req.ProductConfigRequest;
import com.kly.service.ProductService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 产品配置相关服务类
 * @author linqu
 */
@Service("productService")
public class ProductServiceImpl implements ProductService {

    @Resource
    ProductDao productDao;
    @Resource
    ProductCategoryDao productCategoryDao;
    @Resource
    ProductBenefitsDao productBenefitsDao;
    @Resource
    BenefitsDao benefitsDao;
    @Resource
    ProductMapper mapper;

    /**
     * 获取产品配置
     * @param appCode 应用码
     * @param productCategory 产品类目：1、会员产品，2、会话产品，3、私密相册、4、私密视频
     * @return 返回产品配置
     */
    @Override
    public Response<List<ProductDto>> queryProductsByProductCategory(String appCode, Integer productCategory) {

        final List<ProductEntity> productEntities = productDao.selectByProductCategory(appCode, productCategory);
        if (CollectionUtils.isEmpty(productEntities)) {
            return Response.ok();
        }

        final List<ProductDto> products = productEntities.parallelStream().map(o -> {
            ProductDto dto = ProductDto.builder().build();
            BeanUtils.copyProperties(o, dto);
            return dto;
        }).collect(Collectors.toList());

        return Response.ok(products);
    }

    @Override
    public Response<ProductDto> queryProductsByProductCode(String appCode, String productCode) {
        ProductEntity product = productDao.getProduct(appCode, productCode);
        if (product == null) {
            return Response.error(TradeResultStatus.INVALID_PRODUCT_CODE);
        }
        ProductDto productDto = mapper.toDto(product);
        return Response.ok(productDto);
    }

    /**
     * 获取产品配置
     */
    @Override
    public Response<List<AllProductDto>> queryAllProduct(String appCode) {
        if (StringUtils.isBlank(appCode)) {
            return Response.ok();
        }

        final List<ProductCategoryEntity> productCategoryEntities = productCategoryDao.getProductCategoryEntities(appCode);

        // 判断是否存在产品类目
        if (CollectionUtils.isEmpty(productCategoryEntities)) {
            return Response.ok();
        }
        // 判断是否存在产品
        final List<ProductEntity> productEntities = productDao.selectAllProducts(appCode);
        if (CollectionUtils.isEmpty(productEntities)) {
            return Response.ok();
        }

        final List<AllProductDto> allProductList = productCategoryEntities.parallelStream().map(o -> {
            // 获取productCategory 对应的产品列表
            final List<ProductDto> products = getProductDtos(productEntities, o.getProductCategory());
            // 获取产品配置详情信息
            final JSONArray productDetails = getProductDetails(productEntities, o.getProductCategory());
            return getAllProductDto(appCode, o, products, productDetails);
        }).collect(Collectors.toList());

        return Response.ok(allProductList);

    }

    @Override
    public Response<List<ProductBenefitDto>> listProductBenefit(String appCode, Integer productCategory) {
        if (StringUtils.isBlank(appCode) || productCategory == null) {
            return Response.ok();
        }

        List<ProductBenefitsEntity> productBenefitsEntities = productBenefitsDao.listProductBenefit(appCode, productCategory);
        if (CollectionUtils.isEmpty(productBenefitsEntities)) {
            return Response.ok();
        }

        final List<ProductBenefitDto> productBenefitDtos = productBenefitsEntities.stream().map(o -> {
            final ProductBenefitDto dto = ProductBenefitDto.builder().build();
            BeanUtils.copyProperties(o, dto);
            dto.setBenefitCode(Integer.valueOf(o.getBenefitCode()));
            return dto;
        }).collect(Collectors.toList());

        return Response.ok(productBenefitDtos);

    }

    @Override
    public Response addProductBenefit(String appCode, Integer productCategory, Integer benefitCode, Integer limitNum) {
        final ProductBenefitsEntity productBenefit = productBenefitsDao.getProductBenefit(appCode, productCategory, benefitCode);
        if (productBenefit == null) {
            final ProductBenefitsEntity addBenefit = addProductBenefit(appCode, benefitCode, limitNum);
            if (addBenefit != null && addBenefit.getId() != null) {
                return Response.ok();
            }
            return Response.error("Add benefit fail");
        }
        productBenefit.setLimitQuantity(limitNum == null ? 0 : limitNum);
        productBenefitsDao.updateByPrimaryKey(productBenefit);
        return Response.ok();
    }

    @Override
    public Response modifyProductBenefit(ProductConfigRequest productConfigRequest) {
        final List<ProductBenefitsEntity> productBenefitList = productBenefitsDao.listProductBenefitByBenefitCode(productConfigRequest.getAppCode(), productConfigRequest.getBenefitCode());
        if (CollectionUtils.isEmpty(productBenefitList)) {
            return Response.ok();
        }
        for (ProductBenefitsEntity entity : productBenefitList) {
            entity.setTip(productConfigRequest.getTip());
            entity.setContent(productConfigRequest.getContent());
            entity.setIcon(productConfigRequest.getIcon());
            entity.setEnableFlag(productConfigRequest.getShowFlag());

            final String benefitDesc = entity.getBenefitCode();
            if (StringUtils.isNotEmpty(benefitDesc)) {
                final ProductCategoryDto.Subscriptions subDto = JSONUtil.toBean(benefitDesc, ProductCategoryDto.Subscriptions.class);
                subDto.setContent(productConfigRequest.getContent());
                entity.setBenefitDesc(JSONUtil.toJsonStr(subDto));
            }

            productBenefitsDao.updateByPrimaryKey(entity);
        }

//        productBenefitsDao.updateByBenefitCode(productConfigRequest.getAppCode(), productConfigRequest.getBenefitCode(), productConfigRequest.getTip(), productConfigRequest.getContent(), productConfigRequest.getIcon(), productConfigRequest.getShowFlag());

        return Response.ok();
    }

    @Override
    public Response removeProductBenefit(String appCode, Integer benefitCode) {
        productBenefitsDao.removeProductBenefit(appCode, benefitCode);
        return Response.ok();
    }

    private ProductBenefitsEntity addProductBenefit(String appCode, Integer benefitCode, Integer limitNum) {
        final BenefitsEntity benefits = benefitsDao.getBenefits(benefitCode);
        if (benefits == null) {
            throw new ApplicationException("Illegal parameter: benefitCode not exists");
        }

        ProductBenefitsEntity newBenefit = new ProductBenefitsEntity();
        newBenefit.setAppCode(appCode);
        newBenefit.setBenefitCode(String.valueOf(benefitCode));
        newBenefit.setBenefitName(benefits.getBenefitName());
        newBenefit.setBenefitNameCn(benefits.getBenefitNameCn());
        newBenefit.setSortBy(1);
        newBenefit.setLimitQuantity(limitNum == null ? 0 : limitNum);
        newBenefit.setIsLimited(1);
        return productBenefitsDao.insert(newBenefit);
    }

    private AllProductDto getAllProductDto(String appCode, ProductCategoryEntity o, List<ProductDto> products, JSONArray productDetails) {
        final AllProductDto productDto = AllProductDto.builder().appCode(appCode).productCategory(o.getProductCategory())
                .productCategoryName(o.getProductCategoryName()).productCategoryDesc(o.getCategoryDesc()).productExt(productDetails).build();
        productDto.setProductList(products);
        return productDto;
    }

    private List<ProductDto> getProductDtos(List<ProductEntity> productEntities, Integer productCategory) {

        final List<ProductEntity> productList = getProductListByProductCategory(productEntities, productCategory);
        if (CollectionUtils.isEmpty(productList)) {
            return Lists.newArrayList();
        }
        return productList.parallelStream().map(o1 -> {
            ProductDto dto = ProductDto.builder().build();
            BeanUtils.copyProperties(o1, dto);
            return dto;
        }).collect(Collectors.toList());
    }

    private JSONArray getProductDetails(List<ProductEntity> productEntities, Integer productCategory) {

        final List<ProductEntity> productList = getProductListByProductCategory(productEntities, productCategory);
        if (CollectionUtils.isEmpty(productList)) {
            return new JSONArray();
        }
        JSONArray productCofnigs = new JSONArray();
        for (ProductEntity entity : productList) {
            final String productConfig = entity.getProductConfig();
            if (StringUtils.isNotBlank(productConfig)) {
                final JSONObject config = JSONObject.parseObject(productConfig);
                productCofnigs.add(config.getJSONObject("productDetail"));
            }
        }
        return productCofnigs;

    }

    private List<ProductEntity> getProductListByProductCategory(List<ProductEntity> productEntities, Integer productCategory) {
        return productEntities.parallelStream()
                .filter(p -> p.getProductCategory().equals(productCategory))
                .collect(Collectors.toList());
    }

}
